package com.shm.leetcode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author: shm
 * @dateTime: 2020/9/18 11:38
 * @description: 47. 全排列 II
 * 给定一个可包含重复数字的序列，返回所有不重复的全排列。
 *
 * 示例:
 *
 * 输入: [1,1,2]
 * 输出:
 * [
 *   [1,1,2],
 *   [1,2,1],
 *   [2,1,1]
 * ]
 */
public class PermuteUnique {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> temp = new ArrayList<>();
    public List<List<Integer>> permuteUnique(int[] nums) {
        Arrays.sort(nums);
        boolean[] visited = new boolean[nums.length];
        dfs(nums,visited);
        return res;
    }

    public void dfs(int[] nums,boolean[] vis){
        if (temp.size()==nums.length){
            res.add(new ArrayList<>(temp));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            /**
             * @author: shm
             * @dateTime: 2020/9/18 13:29
             * @description: 但是什么又是“使用过”，我们把排列问题抽象为树形结构之后，“使用过”在这个树形结构上是有两个维度的，一个维度是同一树枝上使用过，一个维度是同一树层上使用过。
             *
             * 没有理解这两个层面上的“使用过” 是造成大家没有彻底理解去重的根本原因。
             * 那么排列问题，既可以在 同一树层上的“使用过”来去重，也可以在同一树枝上的“使用过”来去重！
             * 理解这一本质，很多疑点就迎刃而解了。
             *
             * 首先把示例中的 [1,1,2]，抽象为一棵树，然后在同一树层上对nums[i-1]使用过的话，进行去重如图：
             * 图中我们对同一树层，前一位（也就是nums[i-1]）如果使用过，那么就进行去重。
             *
             * 拓展
             * 大家发现，去重最为关键的代码为：
             *
             * if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
             *     continue;
             * }
             * 可是如果把 used[i - 1] == true 也是正确的，去重代码如下：
             *
             *
             * if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == true) {
             *     continue;
             * }
             * 这是为什么呢，就是上面我刚说的，如果要对树层中前一位去重，就用used[i - 1] == false，如果要对树枝前一位去重用用used[i - 1] == true。
             *
             * 对于排列问题，树层上去重和树枝上去重，都是可以的，但是树层上去重效率更高！
             *
             * 这么说是不是有点抽象？
             *
             * 来来来，我就用输入: [1,1,1] 来举一个例子。
             *
             * 树层上去重(used[i - 1] == false)，的树形结构如下：
             *
             * 树枝上去重（used[i - 1] == true）的树型结构如下：
             *
             * 作者：carlsun-2
             * 链接：https://leetcode-cn.com/problems/permutations-ii/solution/47-quan-pai-lie-iiche-di-li-jie-pai-lie-zhong-de-q/
             */
            if (i>0&&nums[i]==nums[i-1]&&!vis[i-1]){
                continue;
            }
            if (!vis[i]){
                temp.add(nums[i]);
                vis[i] = true;
                dfs(nums,vis);
                vis[i] = false;
                temp.remove(temp.size()-1);
            }
        }
    }


    public static void main(String[] args) {
        PermuteUnique permuteUnique = new PermuteUnique();
        permuteUnique.permuteUnique(new int[]{1,1,2});
    }
}
